#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>
#include <CAddStuInfoDialog.h>
#include <QDebug>
#include "CQComboBoxDelegate.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , m_dataSource(NULL)
    , m_standardModel(NULL)
    , m_addStuInfo(NULL)
{
    ui->setupUi(this);
    //实例化数据源
    m_dataSource = new CDataSourceSQLite();

    //实例化
    m_addStuInfo = new CAddStuInfoDialog(this);
    //关联槽函数
    connect(m_addStuInfo, &CAddStuInfoDialog::sig_addInfo, this, &Widget::slot_addInfo);
    connect(m_addStuInfo, &CAddStuInfoDialog::sig_updateInfo, this, &Widget::slot_updateInfo);

    //初始化界面
    initUi();
}

Widget::~Widget()
{
    delete m_dataSource;
    delete ui;
}

void Widget::initUi()
{
    //实例化model
    m_standardModel = new QStandardItemModel(this);
    connect(m_standardModel, &QStandardItemModel::itemChanged, this, &Widget::slot_itemChanged);

    //实例化自定义委托并绑定到界面里
    m_spinBoxDelegate = new CQSpinBoxDelegate(this);
    ui->tb_stuInfo->setItemDelegateForColumn(4, m_spinBoxDelegate);

    m_comboBoxDelegate = new CQComboBoxDelegate(this);
    ui->tb_stuInfo->setItemDelegateForColumn(2, m_comboBoxDelegate);



    //实例化菜单及菜单项
    m_menu = new QMenu(this);
    m_actUpdate = new QAction("修改", m_menu);
    m_actDelete = new QAction("删除", m_menu);
    m_menu->addAction(m_actUpdate);
    m_menu->addAction(m_actDelete);
    //设置菜单弹出策略
    ui->tb_stuInfo->setContextMenuPolicy(Qt::CustomContextMenu);
    //设置实现右键弹出菜单槽函数
    connect(ui->tb_stuInfo, &QTableView::customContextMenuRequested, this, &Widget::slot_popMenu);
    //设置修改和删除槽函数
    connect(m_actUpdate, &QAction::triggered, this, &Widget::slot_actUpdate);
    connect(m_actDelete, &QAction::triggered, this, &Widget::slot_actDelete);

    //查询数据
    QList<CStuInfo> stuInfoList;
    bool res = m_dataSource->selectStuinfos(stuInfoList);
    if(!res)
    {
        QMessageBox::information(this, "提示", "查询学生信息失败!");
        return;
    }

    for (int i = 0; i < stuInfoList.size(); i++)
    {
        appendToModel(stuInfoList[i]);
    };

    //添加表头
    QStringList headerList;
    headerList << "学号" << "姓名" << "性别" << "手机号" << "cet4" << "gpa" << "综合成绩";
    m_standardModel->setHorizontalHeaderLabels(headerList);
    //隐藏垂直表头
    ui->tb_stuInfo->verticalHeader()->setVisible(false);
    //设置每列的宽度
    for(int col = 0; col < CONST_COLUMN_SIZE; col++)
    {
        ui->tb_stuInfo->setColumnWidth(col, (width() - 25) / 7);
    }

    //把数据放在TableView中
    ui->tb_stuInfo->setModel(m_standardModel);
}

bool Widget::appendToModel(CStuInfo &stuInfo)
{
    QStandardItem *itemId = new QStandardItem(QString("%1").arg(stuInfo.id(), 4, 10, QLatin1Char('0')));
    itemId->setCheckable(true); //增加复选框
    itemId->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//数据水平垂直居中
    itemId->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemName = new QStandardItem(stuInfo.name());
    itemName->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    itemName->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemSex = new QStandardItem(stuInfo.sex());
    itemSex->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    //itemSex->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemPhone = new QStandardItem(stuInfo.phone());
    itemPhone->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    itemPhone->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemCet4 = new QStandardItem(QString::number(stuInfo.cet4()));
    itemCet4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    //itemCet4->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemGpa = new QStandardItem(QString::number(stuInfo.gpa()));
    itemGpa->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    itemGpa->setEditable(false);//设置为不可编辑状态

    QStandardItem *itemOverallScore = new QStandardItem(QString::number(stuInfo.overallScore()));
    itemOverallScore->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    itemOverallScore->setEditable(false);//设置为不可编辑状态

    QList<QStandardItem*> rowItem;
    rowItem.append(itemId);
    rowItem.append(itemName);
    rowItem.append(itemSex);
    rowItem.append(itemPhone);
    rowItem.append(itemCet4);
    rowItem.append(itemGpa);
    rowItem.append(itemOverallScore);

    m_standardModel->appendRow(rowItem);
    return true;
}


void Widget::on_btn_Add_clicked()
{
    m_addStuInfo->setIsUpdate(false);
    m_addStuInfo->show();
}

bool Widget::slot_addInfo(CStuInfo &stuInfo)
{
    bool res = m_dataSource->addStuInfo(stuInfo);
    if(!res)
    {
        QMessageBox::information(this, "提示", "插入数据库失败!");
        return false;
    }
    qDebug() << "插入数据库成功!";

    appendToModel(stuInfo);
    return true;
}

bool Widget::slot_updateInfo(CStuInfo &stuInfo)
{
    bool res = m_dataSource->updateStuInfo(stuInfo);
    if(!res)
    {
        QMessageBox::information(this, "提示", "修改数据库失败!");
        return false;
    }

    //让修改后的数据显示在表格中
    int row = ui->tb_stuInfo->currentIndex().row();
    m_standardModel->setData(m_standardModel->item(row, 1)->index(),stuInfo.name());
    m_standardModel->setData(m_standardModel->item(row, 2)->index(),stuInfo.sex());
    m_standardModel->setData(m_standardModel->item(row, 3)->index(),stuInfo.phone());
    m_standardModel->setData(m_standardModel->item(row, 4)->index(),stuInfo.cet4());
    m_standardModel->setData(m_standardModel->item(row, 5)->index(),stuInfo.gpa());
    m_standardModel->setData(m_standardModel->item(row, 6)->index(),stuInfo.overallScore());

    qDebug() << "修改数据库成功!";
    QMessageBox::information(this, "提示", "修改数据成功!");
    return true;
}

bool Widget::slot_itemChanged(QStandardItem *item)
{
    if(m_standardModel->indexFromItem(item).column() > 0)
    {
        //获取数据变更的行
        int row = m_standardModel->indexFromItem(item).row();
        CStuInfo stuInfo1;
        stuInfo1.setId(m_standardModel->item(row, 0)->data(Qt::DisplayRole).toInt());
        stuInfo1.setName(m_standardModel->item(row, 1)->data(Qt::DisplayRole).toString());
        stuInfo1.setSex(m_standardModel->item(row, 2)->data(Qt::DisplayRole).toString());
        stuInfo1.setPhone(m_standardModel->item(row, 3)->data(Qt::DisplayRole).toString());
        stuInfo1.setCet4(m_standardModel->item(row, 4)->data(Qt::DisplayRole).toInt());
        stuInfo1.setGpa(m_standardModel->item(row, 5)->data(Qt::DisplayRole).toDouble());
        stuInfo1.setOverallScore(m_standardModel->item(row, 6)->data(Qt::DisplayRole).toDouble());
        m_dataSource->updateStuInfo(stuInfo1);
        return false;
    }
    for(int row = 0; row < m_standardModel->rowCount(); row++)
    {
        if(m_standardModel->item(row)->checkState() != Qt::Checked)
        {
            ui->chk_SelectAll->setChecked(false);
            return false;
        }
    }
    ui->chk_SelectAll->setChecked(true);
    return true;
}

bool Widget::slot_popMenu(const QPoint &pos)
{
    if(m_standardModel->itemFromIndex(ui->tb_stuInfo->indexAt(pos)) != NULL)
    {
        m_menu->exec(QCursor::pos());
    }
    return true;
}

bool Widget::slot_actUpdate()
{
    m_addStuInfo->setIsUpdate(true);//修改功能标识
    int row = ui->tb_stuInfo->currentIndex().row();
    int id = m_standardModel->item(row, 0)->text().toInt();
    QString name = m_standardModel->item(row, 1)->text();
    QString sex = m_standardModel->item(row, 2)->text();
    QString phone = m_standardModel->item(row, 3)->text();
    int cet4 = m_standardModel->item(row, 4)->text().toInt();
    double gpa = m_standardModel->item(row, 5)->text().toDouble();

    m_addStuInfo->display(id, name, sex, phone, cet4, gpa);
    m_addStuInfo->show();
    return true;
}

bool Widget::slot_actDelete()
{
    int row = ui->tb_stuInfo->currentIndex().row();
    int id = m_standardModel->item(row, 0)->text().toInt();
    m_dataSource->deleteStuInfo(id);
    m_standardModel->removeRow(row);
    return true;
}

void Widget::on_chk_SelectAll_clicked(bool checked)
{
    for(int row = 0; row < m_standardModel->rowCount(); row++)
    {
        if(checked)
        {
            m_standardModel->item(row)->setCheckState(Qt::Checked);
        }
        else
        {
             m_standardModel->item(row)->setCheckState(Qt::Unchecked);
        }
    }
}

void Widget::on_btn_Delete_clicked()
{
    //先判断表中勾选了哪些学号
    QMap<int, QStandardItem*> delRowsMap; //待删除的行和对应的id，QStandarditem*泛指第一列的数据项
    for(int row = 0; row < m_standardModel->rowCount(); row++)
    {
        QStandardItem* item = m_standardModel->item(row);
        if(item->checkState() == Qt::Checked)
        {
            delRowsMap.insert(row, item);
        }
    }

    if(delRowsMap.size() < 1)
    {
        return;
    }

    //给出提示 让用户确认是否删除
    int res = QMessageBox::information(this, "提示", "确定要删除吗？", QMessageBox::Yes | QMessageBox::No);
    if(res == QMessageBox::No) return;

    //1.删除数据库中的数据
    //注意：删除的时候要从后往前删除，从前面删除，后面的编号会变化，无法完全删除
    QList<int> keyList = delRowsMap.keys();
    for(int i = keyList.size() - 1; i >= 0; i--)
    {
        if(m_dataSource->deleteStuInfo(delRowsMap.value(keyList[i])->text().toInt()))
        {
            //删除窗口中的数据
            m_standardModel->removeRow(keyList[i]);
        }
    }

}
